home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
COMMUNIC
/
1572A.ZIP
/
KMT_IBM3.ZIP
/
MSGIBM.ASM
next >
Wrap
Assembly Source File
|
1989-07-10
|
120KB
|
2,430 lines
Name msgibm
; File MSGIBM.ASM
; Tektronix emulator for use with MS Kermit/IBM.
; Edit history:
; Last edit 21 Nov 1988
; 21 Nov 1988 Version 2.32
; 16 Sept 1988 Also look in 0fc00:50h for AT&T logo.
; 1 July 1988 Version 2.31
; 22 May 1988 Add support for ESC [ Pn ; Pn m (ANSI) screen coloring.
; 22 March 1988 Add global byte Tekgraf which forces graphics board type
; 0=auto-sensing, 1=cga, 2=ega, 3=VGA, 4=Hercules, 5=ATT. Tekgraf stored
; here and set in file MSX by Set Term Graphics <board type>. Permit chars
; to overlap existing pixels. [jrd]
; 27 Feb 1988 Add tests for Toshiba T3100 (tnx for assist from Rob Preuss),
; for Olivetti M28/AT&T 6300+, and for DEC VAXmate II (tnx to Frank da Cruz)
; Add pointer based dispatch to character-font drawing routine. Add tests
; for stdin being a file rather than a device (keyboard). [jrd]
; 27 Jan 1988 Supress GIN and Status echos with Bypass byte. Bypass is reset
; by receipt of BEL, LF, CR, US, escape sequences, terminal reset.
; Bypass is set by receipt of ESC Control-E, ESC Control-X, ESC Control-Z.
; Make GIN mode crosshairs remember last GIN mode postion until the terminal
; is reset; make major steps smaller. Add ESC query-mark stands for DEL.
; Make Horizontal Tab (Control-I) a non-printing cursor control character
; to move right one column (with line wrap). Let real Hercules boards use
; both pages of memory (clones behave differently), tnx to Daniel Gruner.
; 1 Jan 1988 version 2.30
; 31 Dec 1987 change name from msvibm to msgibm for final release. [jrd]
; 29 Dec 1987 Add ESC [ ? 3 8 l as exit Tek mode command, from VT340's.[jrd]
; 26 Dec 1987 Add test to absorb echo of crosshairs report. [jrd]
; 22 Dec 1987 Revise parsing rules to make an escape sequence be a temporary
; interruption to the current command (except Clear Screen seq). [jrd]
; Add Control-C and Control-Break as non-reporting exits from GIN mode. [jrd]
; 21 Dec 1987 Add AT&T 6300, Olivetti M24 presence tests and run code. [jrd]
; 16 Dec 1987 Correct screen coloring for 64KB mono/med res color egas. [jrd]
; 4 Dec 1987 Add quirks for Environments, such as TopView, Windows. [jrd]
; 3 Dec 1987 Let 128KB EGA boards save screens. [jrd]
; 30 Nov 1987 Add relative plotting, thanks to help from Bob Parks. [jrd]
; 24 Nov 1987 Add dashed line patterns. [jrd]
; 21 Nov 1987 Add full color background. [jrd]
; 15 Nov 1987 Do screen clears manually because a Bios mode-set keeps
; interrupts off long enough to miss serial port characters. Make crosshairs
; smaller. [jrd]
; 8 Nov 1987 Modularize line drawing using Bresneham's algorithm, use pointers
; to action routines for different board types. Add screen save/restore.
; Do display board presence tests. Add FS as point plot introducer. Allow
; for virtual screens when operating under Environments (Windows, etc). [jrd]
; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
; material. [jrd]
;==============================================================================
; Original version for TI Pro computers by
; 12-Dec-84 Joe Smith, CSM Computing Center, Golden CO 80401
; adapted to IBM PC June 1987 by Brian Holley,
; Faculty of Economics and Politics
; University of Cambridge, England
; Email: BJH6@UK.AC.CAM.PHX
; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
;
; Description of Tektronix commands
;
; ESCAPE-CONTROL-E (ENQ) requests a status report
; ESCAPE-FORMFEED erases the screen.
; ESCAPE-CONTROL-X turns on bypass mode (no screen characters).
; ESCAPE-CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
; ESCAPE-? is replaced by DEL code, to assist line plots with 7 bit systems.
; ESCAPE [ Pn ; Pn m set screen colors. Pn = 30 + sum of colors for foregnd,
; 40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
; intensity. Colors are red = 1, green = 2, blue = 4.
; ESCAPE [ ? 3 8 l exits Tek mode and returns to host text terminal type
; (VT102 if none defined yet). This is an extension from DEC VT340's.
; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
; RS P means move pen down, following letters:A, E, D, F, B, J, H, I mean
; move right, right and up, up, left and up, left, left and down, down, and
; right and down, respectively. Ex: RS <space> J J J means move three Tek
; positions left and down with the pen up (invisibly).
; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
; ignored if we are emulating a full Tek terminal rather than a sub mode
; of DEC or Heath.
; FF erases screen.
; ESCAPE letter, where letter is accent grave (`), a-e sets the line drawing
; pattern until reset to solid lines (same as escape accent) by command or
; a terminal reset.
; where
; ENQ = Control E
; ESC = Control [ (left square bracket)
; FF = Control L
; FS = Control \ (backslash)
; GS = Control ] (right square bracket)
; RS = Control ^ (caret)
; US = Control _ (underscore)
;
; The plot commands are characters which specify the absolute position to move
; the beam. All moves except the one immediately after the GS character
; (Control-]) are with a visible trace.
;
; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
; although only 0 to 780 are visible for Y due to screen geometry. The screen
; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
;
; For 4014-like devices - The positions are from 0 to 4096, but each movement
; is a multiple of 4 positions unless the high-resolution LSBXY are sent. This
; makes it compatible with the 4010 in that a full sized plot fills the screen.
;
; HIX,HIY = High-order 5 bits of position
; LOX,LOY = Middle-order 5 bits of position
; LSBXY = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
;
; Hi Y Lo Y Hi X LSBXY Characters sent (Lo-X always sent)
; ---- ---- ---- ----- ----------------------------------
; Same Same Same Same Lo-X
; Same Same Same Diff LSB, Lo-Y, Lo-X 4014
; Same Same Diff Same Lo-Y, Hi-X, Lo-X
; Same Same Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Same Diff Same Same Lo-Y, Lo-X
; Same Diff Same Diff LSB, Lo-Y, Lo-X 4014
; Same Diff Diff Same Lo-Y, Hi-X, Lo-X
; Same Diff Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Same Same Same Hi-Y, Lo-X
; Diff Same Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Same Diff Same Hi-Y, Lo-Y, Hi-X, Lo-X
; Diff Same Diff Diff Hi-Y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Diff Same Same Hi-Y, Lo-Y, Lo-X
; Diff Diff Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Diff Diff Same Hi-y, Lo-Y, Hi-X, Lo-X
; Diff Diff Diff Diff Hi-y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Offset for byte: 20h 60h 60h 20h 40h
;
; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y. LO-Y must
; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
; accept LO-Y. The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
;
;
;
; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
; startup code in tekini and is maintained in this file. Internal variable
; inited remembers if we have a graphics screen saved, etc.
; TEKINI must be called when entering the emulator to establish the graphics
; screen mode and to calculate the screen dimensions.
; TEKRINT reinitialize complete emulator.
; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
; external procedures have detected an Escape Control-L sequence. An implicit
; initialization is done if necessary.
; TEKEMU is the normal entry point to pass a received character to the emulator.
; It too will do an implicit initialization, if required.
; TEKCLS clears the graphics screen, but only if the emulator is active.
; The emulator remains active during Connect mode Help, Status, and other
; interrupts which do not change the terminal type.
public tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
public tekcls, tekesc, tekflg ; used by msz file
include mssdef.h
ENQ equ 05h ; ^E ENQ for TEK enquiries
CAN equ 18h ; ^X to return to ANSI mode
ESCZ equ 1Ah ; SUB, ESC-^Z triggers crosshairs
VT equ 0bh ; ^K go up one line
FS equ 1ch ; ^\ for point plot mode
GS equ 1Dh ; ^] draw line (1st move is invisible)
RS equ 1Eh ; ^^ for incremental line plot mode
US equ 1Fh ; ^_ (underscore) returns to text mode
accent equ 60h ; accent grave
txtmode equ 4 ; text mode for TEKTRONIX status
maxtekx equ 1024 ; horizontal and
maxteky equ 780 ; vertical resolution of TEK 4010
screen equ 10h ; IBM Bios screen call
uparr equ 72 ; DOS scan codes for arrow keys
dnarr equ 80
lftarr equ 75
rgtarr equ 77
homscn equ 71 ; DOS home screen scan code
shuparr equ '8' ; ascii codes for shifted arrows
shdnarr equ '2'
shlftarr equ '4'
shrgtarr equ '6'
; Graph_mode for different systems:
cga equ 6 ; highest resolution mode for CGA
mono equ 7 ; real monochrome display adapter
colorega equ 14 ; Low-res mode, color EGA
monoega equ 15 ; mono ega needs mode 15
ega equ 16 ; Hi-res mode - EGA
olivetti equ 72 ; Olivetti's Hi-res - 50 lines text
toshiba equ 74h ; Toshiba T3100, like Olivetti
vaxmate equ 0D0h ; DEC VAXmate II, like Olivetti
hercules equ 255 ; pseudo mode for Hercules graphics
; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above
; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5.
; The code will scale everything appropriately for the new screen size, but
; there will be insufficient memory to retain the entire graphics image.
; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps.
segega equ 0a000h ; segments of display memory, EGA,VGA
segcga equ 0b800h ; CGA, AT&T/Olivetti and relatives
seghga equ 0b000h ; HGA
segmono equ 0b000h ; Monochrome
; Hercules equates:
index equ 03b4h ; 6845 index register
cntrl equ 03b8h ; Display mode control port
hstatus equ 03bah ; status port
scrn_on equ 8 ; bit to turn screen on
grph equ 2 ; graphics mode
text equ 20h ; text mode
config equ 03bfh ; configuration port
genable equ 1+2 ; enable graphics (1) on two pages (2)
hiy equ 1 ; codes for Tek graphics components
loy equ 2
hix equ 4
lox equ 3
datas segment public 'datas'
extrn flags:byte, portval:word, rxtable:byte, vtemu:byte
extrn tv_mode:byte
xmult dw ? ; scaling factor for x is
xdiv dw ? ; xmult/xdiv
ymult dw ? ; scaling factor for y is
ydiv dw ? ; ymult/ydiv
xmax dw ? ;
ybot dw ? ;
; required for Hercules screen handling
gtable db 35h,2dh,2eh,7 ; bytes for 6845 controller
db 5bh,2,57h,57h ; - graphics mode
db 2,3,0,0
ttable db 61h,50h,52h,0fh ; bytes for 6845 controller
db 19h,6,19h,19h ; - text mode
db 2,0dh,0bh,0ch
attlogo db 'OLIVETTI' ; Olivetti M24/28, AT&T 6300 rom id
attlen equ $-attlogo ; length
toshlogo db ' TT33110000 TTOOSSHHIIBBAA' ; Toshiba T3100 logo
toshlen equ $-toshlogo ; length
declogo db 'Copyright Digital Equipment Corp' ; DEC VAXmate
declen equ $-declogo
ttstate dw tektxt ; state machine control pointer
prestate dw 0 ; previous state, across interruptions
visible db 0 ; 0 to move, 1 to draw a line
tek_hiy dw 0 ; Y coordinate in Tektronix mode
tek_loy db 0
tek_hix dw 0 ; X coordinate in Tektronix mode
tek_lox db 0
tek_lsb db 0 ; Low-order 2 bits of X + low Y
; (4014 mode)
status db 0
lastc db 0 ; last x/y coord fragment seen
masktab db 80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
; dashed line patterns
linetab dw 0ffffh ; ESC accent 11111111 11111111
dw 0aaaah ; ESC a 10101010 10101010
dw 0f0f0h ; ESC b 11110000 11110000
dw 0fafah ; ESC c 11111010 11111010
dw 0ffcch ; ESC d 11111111 11001100
dw 0fc92h ; ESC e 11111100 10010010
linepat dw 0ffffh ; active line pattern, from above
;End of init data
IDSEQ dw tekem ; address of response to terminal
CTLTAB dw 0 ; .. inquiry
tekem db 'IBM_TEK' ; .. and the response
db escape,'/Z',0
x_coord dw 0 ; Tek text char X coordinate
y_coord dw 8 ; Tek text char Y coordinate
xcross dw 0 ; cross hairs to start at centre
ycross dw 0
oldx dw 0 ; Tek coordinates of last point
oldy dw 767 ; initially top left
scalex dw 0 ; PC coord for scaled x value
scaley dw 0 ; for scaled y value
curmode db 0 ; screen mode before graphics
tekgraf db 0 ; Tek graphics board selection (def=auto)
; local variables for LINE plotting routine
graph_mode db 0 ; graphics video mode, default is none
cursor dw 0 ; saved text cursor
inited db 0 ; non-zero if inited (retains page)
tekflg db 0 ; Tek mode active flag
yflags db 0 ; flags byte from msy
flow dw 0 ; flow control word
gpage db 0 ; display adapter graphics page
gfcol db 15 ; graphics foreground colour
gbcol db 0 ; graphics background color
tfcol db 0 ; temp foreground color
tbcol db 0 ; temp background color
lastd db 0,0 ; worker for ESC [ Pn ; Pn m scanner
colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes
moremsg db ' More >'
mormsglen equ $-moremsg ; length of message
ccode db 0 ; temp for holding plot color code
linelen dw 0 ; offset increment between scan lines
putc dw mputc ; ptr to plot a character routine
psetup dw psetupm ; ptr to plot setup routine
pincy dw pincym ; ptr to inc y routine
plotptr dw pltmon ; ptr to dot plot routine
gcplot dw gcgen ; ptr to char plot routine
segscn dw 0b800h ; actual screen segment to use
; ANSI Escape sequence to exit Tek mode
tkoff db escape,'[?38l' ; Exit Tek mode escape sequence
tkofflen equ $-tkoff ; length of sequence
tkoffs db 6 dup (0) ; received chars in rcv'd sequence
tkcnt dw 0 ; counter of matched char in tkoffs
bypass db 0 ; GIN mode bypass condition (0=off)
temp dw 0
; 8*8 font for Hercules and such, CGA, and EGA
; - allows 43 lines, and 80 (90 for Hercules) chars per line.
; all printing (?) characters from <space> to <del> - two characters per line
; 8 bits per scan line, given top line first, 8 scan lines.
font db 0,0,0,0,0,0,0,0, 18h,18h,18h,18h,18h,0,18h,0
db 6ch,6ch,6ch,0,0,0,0,0, 36h,36h,7fh,36h,7fh,36h,36h,0
db 0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
db 38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
db 0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
db 0,18h,7eh,3ch,7eh,18h,0,0, 0,18h,18h,7eh,18h,18h,0,0
db 0,0,0,0,0,18h,18h,30h, 0,0,0,7eh,0,0,0,0
db 0,0,0,0,0,18h,18h,0, 0,06h,0ch,18h,30h,60h,0,0
db 3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
db 3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
db 0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
db 1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
db 3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
db 0,0,18h,18h,0,18h,18h,0, 0,0,18h,18h,0,18h,18h,30h
db 0ch,18h,30h,60h,30h,18h,0ch, 0,0,0,7eh,0,7eh,0,0,0
db 30h,18h,0ch,06h,0ch,18h,30h, 0,3ch,66h,0ch,18h,18h,0,18h,0
db 3ch,66h,6eh,6ah,6eh,60h,3ch, 0,3ch,66h,66h,7eh,66h,66h,66h,0
db 7ch,66h,66h,7ch,66h,66h,7ch, 0,3ch,66h,60h,60h,60h,66h,3ch,0
db 78h,6ch,66h,66h,66h,6ch,78h, 0,7eh,60h,60h,7ch,60h,60h,7eh,0
db 7eh,60h,60h,7ch,60h,60h,60h, 0,3ch,66h,60h,6eh,66h,66h,3ch,0
db 66h,66h,66h,7eh,66h,66h,66h, 0,7eh,18h,18h,18h,18h,18h,7eh,0
db 3eh,0ch,0ch,0ch,0ch,6ch,38h, 0,66h,6ch,78h,70h,78h,6ch,66h,0
db 60h,60h,60h,60h,60h,60h,7eh, 0,63h,77h,7fh,6bh,6bh,63h,63h,0
db 66h,66h,76h,7eh,6eh,66h,66h, 0,3ch,66h,66h,66h,66h,66h,3ch,0
db 7ch,66h,66h,7ch,60h,60h,60h, 0,3ch,66h,66h,66h,6ah,6ch,36h,0
db 7ch,66h,66h,7ch,6ch,66h,66h, 0,3ch,66h,60h,3ch,06h,66h,3ch,0
db 7eh,18h,18h,18h,18h,18h,18h, 0,66h,66h,66h,66h,66h,66h,3ch,0
db 66h,66h,66h,66h,66h,3ch,18h, 0,63h,63h,6bh,6bh,7fh,77h,63h,0
db 66h,66h,3ch,18h,3ch,66h,66h, 0,66h,66h,66h,3ch,18h,18h,18h,0
db 7eh,06h,0ch,18h,30h,60h,7eh, 0,7ch,60h,60h,60h,60h,60h,7ch,0
db 0,60h,30h,18h,0ch,06h,0,0, 3eh,06h,06h,06h,06h,06h,3eh,0
db 18h,3ch,66h,42h,0,0,0,0, 0,0,0,0,0,0,0,0ffh
db 30h,18h,0ch,0,0,0,0,0, 0,0,3ch,06h,3eh,66h,3eh,0
db 60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
db 06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
db 0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
db 60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
db 18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
db 38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
db 0,0,7ch,66h,66h,66h,66h,0, 0,0,3ch,66h,66h,66h,3ch,0
db 0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
db 0,0,6ch,76h,60h,60h,60h,0, 0,0,3eh,60h,3ch,06h,7ch,0
db 30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
db 0,0,66h,66h,66h,3ch,18h,0, 0,0,63h,6bh,6bh,7fh,36h,0
db 0,0,66h,3ch,18h,3ch,66h,0, 0,0,66h,66h,66h,3eh,06h,3ch
db 0,0,7eh,0ch,18h,30h,7eh,0, 0ch,18h,18h,70h,18h,18h,0ch,0
db 18h,18h,18h,0,18h,18h,18h,0, 30h,18h,18h,0eh,18h,18h,30h,0
db 31h,6bh,46h,0,0,0,0,0, 8 dup (0ffh)
datas ends
code segment public 'code'
extrn outchr:near, beep:near, scrseg:near, cmblnk:near
extrn clrmod:near, savescr:near, cptchr:near, pcwait:near
extrn restscr:near, getflgs:near, clrbuf:near, vtans52:near
extrn iseof:near, beep:near
assume cs:code, ds:datas, es:nothing
; Initialise TEK mode by setting high resolution screen, etc
tekini PROC NEAR
push ax ; do presence tests
push bx
push cx
push dx
push si
push di
push es
mov bx,portval ; get port flow control chars:
mov bx,[bx].flowc ; bh=xon, bl=xoff or both are nulls
mov flow,bx ; save here
mov ax,bx ; get flow control word
cmp al,0 ; able to do xoff?
je tekin0 ; e = no
call outmodem ; tell host xoff while we change modes
tekin0: mov bx,vtemu.att_ptr ; emulator screen color ptr
mov al,[bx]
mov gfcol,al ; save foreground color
and gfcol,0fh ; save just foreground bits
and al,70h ; select background color, no bold
mov cl,4
shr al,cl ; get background colors
mov gbcol,al ; set graphics background color
mov ah,15 ; get current screen mode
int screen
cmp al,3 ; in a mono/color text mode (2/3)?
jbe tekin1 ; be = yes
cmp al,mono ; mono text mode (7)?
je tekin1 ; e = yes
cmp tekflg,0 ; are we active as Tek device now?
je tekin1 ; e = no
jmp tekin13 ; yes, don't redo graphics setup
tekin1: mov curmode,al ; save mode here
mov ah,3 ; get cursor position
xor bh,bh ; page 0
int screen
mov cursor,dx ; save position
call savescr ; save text screen
; Presence tests.
tekin2: mov graph_mode,cga ; Color. Assume CGA
mov segscn,segcga ; assume cga screen segment
mov gpage,0 ; graphics page 0 but no page 1
mov putc,offset gputc ; CGA character display routine
mov gcplot,offset gcgen ; General character plot routine
mov psetup,offset psetupc ; CGA plot setup routine
mov plotptr,offset pltcga ; CGA dot plot routine
mov pincy,offset pincyc ; CGA inc y routine
mov xmult,5 ; CGA. Scale TEK to PC by 640/1024
mov xdiv,8 ; so that 0-1023 converts to 0-639
mov xmax,640-8 ; x-coord of rightmost character
mov ymult,10 ; vertical scale for IBM is 200/780
mov ydiv,39 ;
mov ybot,199 ; Bottom of screen is Y=199
mov al,tekgraf ; user video board specification
cmp al,0 ; auto-sensing?
je tekin2c ; e = yes (default)
cmp al,1 ; user wants CGA?
jne tekin2a ; ne = no
jmp tekin13 ; do CGA
tekin2a:cmp al,4 ; user wants Hercules?
jne tekin2b ; ne = no
jmp tekin8 ; do Hercules
tekin2b:cmp al,5 ; user wants AT&T style?
jne tekin2c ; ne = no
jmp tekin7 ; do AT&T kind
; do auto-sensing of display board
; test for EGA
tekin2c:mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
and cl,0fh ; four lower switches
cmp cl,0cH ; Test reserved switch settings
jb tekin3 ; b = ega present
jmp tekin7 ; else no EGA, check other adapters
tekin3: mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
jz tekin3a ; z = yes
jmp tekin7 ; ega is inactive, check others
tekin3a:cmp bl,1 ; is there 128KB on ega board?
jb tekin4 ; b = less, so no screen saves
mov gpage,1 ; >=128 KB, use two graphics pages
tekin4: mov graph_mode,ega ; assume high resolution color
cmp cl,3 ; high resolution color?
je tekin5 ; e = yes
cmp cl,9 ; high resolution color?
je tekin5 ; e = yes
mov graph_mode,monoega ; assume mono monitor on ega board
test bh,1 ; ega mono mode in effect?
jnz tekin5 ; nz = yes
mov graph_mode,colorega ; say ordinary cga on ega board, 64KB
mov gpage,1 ; is enough memory with 200 scan lines
jmp short tekin5a ; use current cga parameters
tekin5: mov ybot,349 ; text screen bottom is 349 on EGA
mov ymult,35 ;
mov ydiv,78 ; scale y by 350/780
tekin5a:mov segscn,segega ; use ega screen segment
mov psetup,offset psetupe ; plot setup routine
mov plotptr,offset pltega ; ega dot plot routine
mov pincy,offset pincye ; inc y routine
mov putc,offset gputc ; character display routine
mov gcplot,offset gcega ; EGA character plot routine
call fixcolor ; correct color mapping for some bds
jmp tekin13 ; end of EGA part, do VGA tests below
tekin7: mov ax,0fc00h ; Olivetti/AT&T 6300, check rom id
mov es,ax
mov di,0 ; start here
mov graph_mode,olivetti ; Olivetti
mov cx,attlen ; length of logo
mov si,offset ATTLOGO ; master string
repe cmpsb ; do a match
je tekin7c ; e = a match
mov di,0050h ; look here too
mov si,offset ATTLOGO
mov cx,attlen
repe cmpsb
je tekin7c ; e = a match
mov di,2014h ; and look here
mov si,offset ATTLOGO
mov cx,attlen
repe cmpsb ; do a match
je tekin7c ; e = a match, else try other types
tekin7a:mov graph_mode,toshiba
mov ax,0f000h ; Check for Toshiba T3100, rom scan
mov es,ax
mov di,0014h ; start here
mov si,offset TOSHLOGO ; master string
mov cx,toshlen ; length
repe cmpsb ; do a match
je tekin7c ; e = a match, else try other types
tekin7b:mov graph_mode,vaxmate ; DEC VAXmate II
mov ax,0f000h ; Check for VAXmate II rom signature
mov es,ax
mov di,0e000h ; start here
mov si,offset DECLOGO ; master string
mov cx,declen ; length
repe cmpsb ; do a match
jne tekin7d ; ne = mismatch, try other types
; Olivetti/AT&T, Toshiba, VAXmate
tekin7c:mov gpage,0 ; only page 0 with 640 by 400 mode
mov segscn,segcga ; use cga screen segment (0b800h)
mov psetup,offset psetupo ; plot setup routine
mov plotptr,offset pltcga ; cga dot plot routine
mov pincy,offset pincyh ; inc y routine (Herc style addresses)
mov putc,offset gputc ; character display routine
mov gcplot,offset gcgen ; General character plot routine
mov ybot,399 ; bottom of screen is y = 399
mov ymult,20 ; vertical scale = 400/780
mov ydiv,39 ; same as cga setup
jmp tekin13
tekin7d:cmp curmode,mono ; mono text mode?
je tekin8 ; e = yes
jmp tekin11 ; ne = no, try cga
; test for Hercules
tekin8: call scrseg ; get screen segment, test Environment
cmp tv_mode,0 ; Environment active?
je tekin8a ; e = no, ok to test for Hercules
jmp tekin10 ; don't do Herc mode, do Mono
tekin8a:mov dx,hstatus ; Herc status port
in al,dx ; read it
mov bl,al ; save here
and bl,80h ; remember retrace bit
mov cx,0ffffh ; do many times (for fast machines)
tekin8b:mov dx,hstatus ; check status port
in al,dx
and al,80h ; select bit
jmp $+2 ; use a little time
cmp bl,al ; did it change?
loope tekin8b ; test again if not
je tekin10 ; e = no change in bit, not Herc
mov graph_mode,hercules ; say have Herc board
mov segscn,seghga ; assume hga screen segment
mov putc,offset gputc ; character display routine
mov gcplot,offset gcgen ; General character plot routine
mov psetup,offset psetuph ; plot setup routine to use
mov plotptr,offset pltcga ; use cga dot plot routine for Herc
mov pincy,offset pincyh ; inc y routine
mov xmult,45 ; Scale TEK to Hercules by 720/1024
mov xdiv,64 ; so that 0-1023 converts to 0-719
mov xmax,720-8 ; x-coord of rightmost character
mov ymult,87 ; vertical scale for Hercules is
mov ydiv,195 ; 348/780
mov ybot,347 ; bottom of screen is y = 347
mov ax,seghga ; segment of Herc video display
mov es,ax
mov al,es:[8000h] ; read original contents, page 1
not byte ptr es:[8000h] ; write new pattern
mov ah,es:[8000h] ; read back
not byte ptr es:[8000h] ; restore original contents
not ah ; invert this too
cmp ah,al ; same (memory present?)
jne tekin9 ; ne = not same, no memory there
mov gpage,1 ; say two pages of display memory
tekin9: jmp tekin13
; set to MONO
tekin10:mov graph_mode,mono ; force monochrome adapter text
mov segscn,segmono ; assume mono screen segment
call scrseg ; Environments: get virtual screen
mov segscn,ax ; seg returned in ax and es:di
mov gpage,0
mov putc,offset mputc ; character display routine
mov psetup,offset psetupm ; plot setup routine to use
mov plotptr,offset pltmon ; use hga dot plot routine
mov pincy,offset pincym ; inc y routine
mov xmult,5 ; Scale TEK to mono by 640/1024
mov xdiv,8 ; so that 0-1023 converts to 0-639
mov xmax,640-8 ; x-coord of rightmost character
mov ymult,10 ; vertical scale for mono is 200/780
mov ydiv,39
mov ybot,200 ; bottom of screen is y = 200 for Bios
jmp tekin13 ; Uses TEXT mode, for safety
; test for CGA
tekin11:mov graph_mode,cga ; set CGA high resolution graphics
mov segscn,segcga ; CGA screen segment
jmp tekin13
; Set Graphics mode
tekin13:cmp graph_mode,hercules ; Hercules?
jne tekin14 ; ne = no
call hgraf ; set Herc graphics mode, clear regen
jmp short tekin16 ; restore screen
tekin14:mov ah,0 ; set screen mode
mov al,graph_mode ; to this screen mode
cmp tekgraf,3 ; user wants "VGA" modes (640x480)?
jne tekin14a ; ne = no
cmp al,monoega ; yes, allow high resolution stuff?
jb tekin14a ; b = no
cmp al,ega ; ditto
ja tekin14a ; a = no
add al,2 ; use modes 17(b/w) and 18(10)(color)
mov ybot,479 ; text screen bottom is 479 on VGA
mov ymult,48
tekin14a:cmp gpage,0 ; only page 0 available?
je tekin15 ; e = yes, and watch for Bios errors
cmp inited,0 ; first time through?
je tekin15 ; e = yes, clear the page of old junk
or al,80h ; save regen buffer (save area too)
tekin15:int screen ; Bios Set Mode.
tekin16:mov tekflg,1 ; starting Tek sub mode
cmp inited,0 ; inited yet?
jne tekin19 ; ne = yes, restore screen
mov ttstate,offset tektxt ; do displayable text
mov prestate,offset tektxt ; set a previous state of text
mov inited,1 ; say we have initialized
mov al,gfcol
mov tfcol,al ; remember current coloring
mov al,gbcol
mov tbcol,al
call tekcls ; clear screen, for ega coloring
jmp short tekin20
tekin19:call tekrest ; restore old graphics screen
mov al,tfcol ; and coloring
mov gfcol,al
mov al,tbcol
mov gbcol,al
tekin20:mov ax,flow ; get flow control word
xchg ah,al ; get xon into al
cmp al,0 ; able to send xon?
je tekin21 ; e = no
call outmodem ; tell host xon
tekin21:clc ; clear carry for success
jmp short tekin23
tekin22:stc ; set carry for failure
tekin23:pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tekini ENDP
TEKRINT proc near ; Tek reinitialization entry point
mov inited,0 ; do complete reinitialization
jmp tekini
TEKRINT endp
;Terminal emulation. Enter with received character in AL.
TEKEMU PROC NEAR ; main emulator
cmp tekflg,0 ; Tek mode active yet? (msz call)
jne tektt1 ; ne = yes
call tekini ; init now
mov ttstate,offset tektxt ; initial state
mov prestate,offset tektxt ; set a previous state of text
jnc tektt1 ; nc = succeeded
ret ; else failed to init, just return
tektt1: and al,7fh ; force Tek chars to be 7 bits
cmp al,0 ; NUL char?
je tekign ; e = yes, ignore it before logging
push ax
call getflgs ; get msy yflags into al
mov yflags,al
test al,capt ; capturing output?
pop ax
jz tektt4 ; z = no, forget this part
push ax ; save char
call cptchr ; give it captured character
pop ax ; restore character and keep going
tektt4: test yflags,trnctl ; debug? if so use tty mode
jz tektt5 ; z = no
cmp al,DEL ; DEL char?
jne tektt4a ; ne = no
mov al,5eh ; make DEL a caret query mark
call outscrn
mov al,3fh ; the query mark
call outscrn
jmp short tekign
tektt4a:cmp al,' ' ; control char?
jae tektt4b ; ne = no
push ax
mov al,5eh ; caret
call outscrn
pop ax
add al,'A'-1 ; make char printable
tektt4b:call outscrn
tekign: ret ; Ignore this character
tektt5: call tkscan ; scan for "ESC [ ? 3 8 l" exit code
tektt5a:cmp al,0 ; null char response?
je tekign ; e = yes, ignore the character
cmp al,' ' ; control code?
jb tektt6 ; b = yes, decode
jmp ttstate ; no, do current state
; Control characters:
tektt6: cmp al,GS ; Line plot command?
jne tektt7 ; ne = no
mov visible,0 ; Next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekline ; expect coordinates next
jmp tektt12
tektt7: cmp al,RS ; Incremental dot command?
jne tektt8 ; ne = no
and status,not txtmode ; set status report
mov ttstate,offset tekrlin ; expect pen command next
jmp tektt12
tektt8: cmp al,FS ; Point plot command?
jne tektt9 ; ne = no
mov visible,0 ; next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekpnt
jmp tektt12
tektt9: cmp al,US ; assert text mode? [bjh]
jne tektt10 ; ne = no
or status,txtmode ; set status report byte
mov ttstate,offset tektxt ; Go to TEKTXT next time
mov bypass,0 ; reset bypass condition
jmp tektt12
tektt10:cmp al,ESCAPE ; Escape?
jne tektt11 ; ne = no
or status,txtmode ; set status report byte
cmp ttstate,offset tekesc ; already in escape state?
je tektt14 ; e = yes, nest no further
push ttstate ; current state
pop prestate ; save here as previous state
mov ttstate,offset tekesc ; next state parses escapes
ret
tektt11:cmp al,CAN ; Control X? (exits Tek sub mode)
jne tektt13 ; ne = no, stay in current state
cmp ttstate,offset tekesc ; ESC Control-X?
je tektt13 ; yes, parse it in tekesc code
mov ttstate,offset tektxt ; back to text mode
test flags.vtflg,tttek ; main Tek emulator?
jnz tektt12 ; nz = yes, ignore the ^X
call tekend ; else exit sub mode
mov tekflg,0 ; clear Tek sub mode flag
tektt12:mov prestate,offset tektxt ; make previous state text
tektt14:ret
tektt13:jmp ttstate ; let someone else worry about this
TEKEMU ENDP
; End TEK emulation, recover previous screen
TEKEND PROC NEAR
cmp tekflg,0 ; Tek sub mode active?
jne teknd0 ; ne = yes
ret ; else return as is.
teknd0: call teksave ; save graphics screen to page 1
cmp graph_mode,hercules ; Hercules?
jne teknd1 ; ne = no
call htext ; yes then set up Hercules text mode
teknd1: mov ah,0 ; set video mode
mov al,curmode ; restore previous screen mode
int screen ; revert to text screen
call restscr ; restore text screen
mov dx,cursor ; saved cursor position
mov bh,0 ; page 0
mov ah,2 ; set cursor
int screen
ret
TEKEND ENDP
; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit
; Tek mode and return to either non-sub mode terminal or to a VT102.
; Plays back unmatched escape sequences. Enter with character in al.
tkscan proc near
and al,7fh ; strip high bit
cmp al,byte ptr tkoff ; start of Tek Off sequence?
jne tkscn1 ; ne = no
call tkscn4 ; playback previously matched chars
mov tkcnt,1 ; count matched chars (one now)
mov tkoffs,al ; save full character, with high bit
mov al,0 ; our temporary response
jmp short tkscnx ; and exit
tkscn1: push bx ; check for char in Tek Off sequence
mov bx,tkcnt ; number of chars matched in Tek Off
mov tkoffs[bx],al ; save this char
cmp al,byte ptr tkoff[bx] ; match expected char in sequence?
pop bx
jne tkscn3 ; ne = no, play back partial match
inc tkcnt ; count new match
mov al,0 ; our temporary response
cmp tkcnt,tkofflen ; matched all char in sequence?
jne tkscnx ; ne = not yet, wait for more
mov tkcnt,0 ; clear counter
cmp flags.vtflg,tttek ; are we a full Tek terminal now?
jne tkscn2 ; ne = no, a submode
call vtans52 ; toggle terminal type, in msyibm
tkscn2: mov al,CAN ; simulate arrival of Control-X
jmp short tkscnx ; all done
tkscn3: call tkscn4 ; playback previously matched chars
mov tkcnt,0 ; reset to no match and exit
tkscnx: ret ; common exit
; local worker procedure
tkscn4: push ax ; save break char (in al)
push cx ; playback partial sequence to screen
mov cx,tkcnt ; number of chars matched before break
jcxz tkscn4b ; z = none
push si
mov si,offset tkoffs ; string to be played back
tkscn4a:cld
lodsb ; get a char into al
push cx
push si ; save these around tektt5a work
call tektt5a ; use it
pop si
pop cx
loop tkscn4a ; do all that came in previously
pop si
tkscn4b:pop cx
pop ax ; recover break char
ret
tkscan endp
TEKTXT proc near ; Dispatch on text characters
cmp al,DEL ; RUBOUT?
jne tektx1 ; ne = no
mov al,bs ; make BS
jmp short tektx7
tektx1: cmp al,CR ; carriage return (^M)?
je tektx9 ; e = yes
tektx2: cmp al,LF ; line feed (^J)?
je tektx9 ; e = yes
tektx3: cmp al,FF ; form feed (^L)?
jne tektx4 ; ne = no
call tekcls ; clear the screen
jmp short tektx8
tektx4: cmp al,VT ; vertical tab (^K)?
je tektx7
cmp al,bell ; bell (^G)?
jne tektx5 ; ne = no
call beep
mov bypass,0 ; clear GIN mode bypass condition
jmp short tektx8
tektx5: cmp al,tab ; horizontal tab (^I)?
je tektx7 ; e = yes
tektx6: cmp al,BS ; backspace (^H)?
je tektx7 ; e = yes
cmp al,' ' ; control char?
jb tektx8 ; b = yes, ignore it
tektx7: cmp bypass,0 ; bypass mode off?
jne tektx8 ; ne = no, it's on so skip display
call OUTSCRN ; output character to the screen
tektx8: ret
tektx9: mov bypass,0 ; clear GIN mode bypass condition
jmp short tektx7
TEKTXT endp
; Process escape sequences. Callable from msz terminal emulator.
; Enter with received character in AL. Escape sequences are generally
; treated as interruptions to the current plotting/text command. Screen
; clearing is the exception by causing a general emulator reset.
TEKESC PROC NEAR
mov bypass,0 ; clear GIN mode bypass condition
mov ttstate,offset tekesc ; in case get here from msz file
cmp tekflg,0 ; Tek mode active yet? (msz call)
jne tekesc1 ; ne = yes
call tekini ; init now
mov prestate,offset tektxt ; set a previous state of text
jnc tekesc1 ; nc = succeeded
ret ; else failed to init, just return
tekesc1:cmp al,'Z' ; ESC-Z Identify?
jne tekesc2 ; ne = no
call SENDID ; Send terminal identification
jmp tekescx
tekesc2:cmp al,FF ; ESC-FF Clear screen?
jne tekesc3 ; ne = no
call tekcls ; Clear screen
mov prestate,offset tektxt ; make previous state text mode
jmp tekescx ; Return to text mode after ESC-FF
tekesc3:cmp al,ESCZ ; ESC-^Z Enter GIN mode?
jne tekesc4 ; ne = no
cmp graph_mode,mono ; Monochrome text mode?
je tekesc3a ; e = yes, no crosshairs in text mode
mov bypass,1 ; turn on GIN mode bypass conditon
call CROSHAIR ; Activate the cross-hairs
jmp tekescx
tekesc3a:call beep ; tell the user we are unhappy
jmp tekescx ; and ignore the command
tekesc4:cmp al,ENQ ; ESC-^E Enquiry for cursor position?
jne tekesc5 ; ne = no
mov bypass,1 ; set bypass mode
call SENDSTAT ; send status
jmp tekescx
tekesc5:cmp al,CAN ; ESC Control-X?
jne tekesc6 ; ne = no
mov bypass,1 ; set bypass condition
jmp tekescx
tekesc6:cmp al,3fh ; query mark? (ESC ? means DEL)
jne tekesc7 ; ne = no
mov al,DEL ; replace with DEL code
jmp tekescx ; and process it as if received.
tekesc7:cmp al,accent ; accent grave, line pattern series?
jb tekesc8 ; b = no
cmp al,65h ; lowercase e?
ja tekescx ; a = beyond line pattern series
push bx
mov bl,al
sub bl,accent ; remove bias
and bl,7 ; eight patterns, roll over excess
mov bh,0
shl bx,1 ; make this a word index
mov bx,linetab[bx] ; get line pattern word
mov linepat,bx ; save in active word
pop bx ; return to previous mode
tekesc8:cmp al,5bh ; right square bracket?
jne tekescx ; ne = no
jmp tekcol ; start coloring scan
tekescx:push ax
mov ax,prestate ; get previous state
mov ttstate,ax ; restore it
or ax,ax ; test for none
pop ax
jz go2text ; z = none, use text mode
clc
ret ; resume previous state
go2text:mov ttstate,offset tektxt ; Go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
clc
ret
TEKESC ENDP
; Parse ESC [ Pn ; Pn m
; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
TEKCOL proc near
mov word ptr lastd,0 ; clear parsing flags used below
mov ttstate,offset tekco1 ; resume parsing below
clc
ret
tekco1: cmp lastd,'3' ; units digit in 30 series?
jne tekco2 ; ne = no
inc lastd+1 ; count argument
sub al,'0' ; ascii to binary
cmp al,7 ; numeric?
jbe tekco1a ; be = yes
jmp tekco10 ; a = no, error
tekco1a:push bx
mov bl,al
mov bh,0
mov al,byte ptr colortb[bx] ; reverse coloring
pop bx
and tfcol,not (7) ; retain intensity bit
or tfcol,al ; remember foreground color
mov lastd,0 ; clear parsing flag
ret
tekco2: cmp lastd,'4' ; units digit in 40 series?
jne tekco4 ; ne = no
inc lastd+1 ; count argument
sub al,'0'
cmp al,7 ; numeric?
ja tekco10 ; a = no, error
push bx
mov bl,al
mov bh,0
mov al,byte ptr colortb[bx] ; reverse coloring
pop bx
mov tbcol,al ; remember background color
mov lastd,0 ; clear parsing flag
ret
tekco4: cmp lastd,0 ; looking for tens digit?
jne tekco10 ; ne = yes, error
cmp al,';' ; separator?
jne tekco5 ; ne = no
ret ; ignore it
tekco5: cmp al,'0' ; remove intensity, set b/w?
jne tekco6 ; ne = no
mov tfcol,7 ; regular white
mov tbcol,0 ; on black
inc lastd+1 ; count argument
ret
tekco6: cmp al,'1' ; intensity bit?
jne tekco7 ; ne = no
and tfcol,not (8)
or tfcol,8 ; set foreground intensity
inc lastd+1 ; count argument
ret
tekco7: cmp al,'m' ; end of sequence
je tekco8 ; e = yes
cmp al,'3'
jb tekco10 ; b = not allowed tens digit
cmp al,'4'
ja tekco10 ; a = not allowed tens digit
mov lastd,al ; remember tens digit
inc lastd+1 ; count argument
ret
tekco8: cmp lastd+1,0 ; number of ansi arguments, zero?
ja tekco9 ; a = no, got some
mov tbcol,0 ; none is same as 0, set b/w
mov tfcol,7
tekco9: mov al,tbcol ; success, store coloring
mov gbcol,al ; set background color
mov al,tfcol
mov gfcol,al ; set foreground color
tekco10:mov word ptr lastd,0 ; clear argument and number of args
call fixcolor ; do special ega corrections
mov al,gfcol ; update these in case error
mov tfcol,al
mov al,gbcol
mov tbcol,al
jmp tekescx ; finish escape state
TEKCOL endp
; Revise screen color codes for ega boards with mono displays and limited
; memory.
fixcolor proc near
cmp graph_mode,ega ; one of these ega modes?
je fixcol0 ; e = yes
cmp graph_mode,colorega
je fixcol0
cmp graph_mode,monoega
je fixcol0
ret ; else ignore color corrections
fixcol0:mov ah,gfcol
mov al,gbcol
cmp graph_mode,monoega ; monochrome display?
jne fixcol3 ; ne = no
test al,7 ; bright backgound?
jnz fixcol1 ; nz = yes
mov ah,1 ; normal foreground
test gfcol,8 ; intensity on?
jz fixcol1 ; z = no
mov ah,5 ; say bright foreground
fixcol1:test al,7 ; black backgound?
jz fixcol2 ; z = yes
mov al,1 ; regular video
fixcol2:cmp ah,al ; same color in both?
jne fixcol3 ; ne = no
mov ah,1 ; make foreground regular
mov al,0 ; and background black
fixcol3:mov gfcol,ah
mov gbcol,al
cmp gpage,0 ; minimal memory (64KB mono and ega)?
ja fixcol4 ; a = no, enough, else strange mapping
mov al,gfcol ; fix coloring to map planes C0 to C1
and al,5 ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
mov ah,al ; make a copy
shl ah,1 ; duplicate planes C0, C2 in C1, C3
or al,ah ; merge the bits
mov gfcol,al ; store proper foreground color
mov al,gbcol ; repeat for background color
and al,5
mov ah,al
shl ah,1
or al,ah
mov gbcol,al
fixcol4:ret
fixcolor endp
TEKLINE proc near ; GS line drawing
call tekxyc ; parse coordinates from input bytes
jnc teklin1 ; nc = not done yet
mov cl,visible ; get moveto or drawto variable
call tekdraw ; move that point
mov visible,1 ; say next time we draw
teklin1:ret
TEKLINE endp
TEKPNT proc near ; FS plot single point
call tekxyc ; parse coordinates
jnc tekpnt1 ; nc = not done yet
mov cl,0 ; do not draw
call tekdraw ; move to the point
mov ax,si ; copy starting point to end point
mov bx,di ; ax,bx,si,di are in PC coordinates
mov cl,1 ; make plot visible
call line ; draw the dot
mov visible,0 ; return to invisibility
tekpnt1:ret
TEKPNT endp
; Decode graphics x,y components. Returns carry set to say have all
; components for a line, else carry clear. Understands 4014 lsb extensions.
; Permits embedded escape sequences.
TEKXYC proc near
cmp al,CR ; Exit drawing on CR,LF,RS,US,FS,CAN
je tekghx ; e = yes, a cr
cmp al,LF ; these terminate line drawing cmds
je tekghx
cmp al,FS ; <FS>
je tekghx
cmp al,RS ; <RS>
je tekghx
cmp al,US ; <US>
je tekghx
cmp al,CAN ; and <CAN>
je tekghx ; BUT ignore other control chars
cmp al,20h ; Control char?
jb tekgh0 ; b = yes, ignore it
cmp al,40h
jb tekgh2 ; 20-3F are HIX or HIY
cmp al,60h ; 40-5F are LOX (causes beam movement)
jb tekgh4 ; 60-7F are LOY
; Extract low-order 5 bits of Y coord
mov ah,tek_loy ; Copy previous LOY to MSB (4014)
mov tek_lsb,ah
and al,1Fh ; LOY is 5 bits
mov tek_loy,al
cmp lastc,loy ; 2nd LOY in a row?
je tekgh1 ; Yes, then LSB is valid
mov tek_lsb,0 ; 1st one, clear LSB
tekgh1: mov lastc,loy ; LOY seen, expect HIX (instead of HIY)
tekgh0: clc ; c clear = not completed yet
ret
tekghx: jmp go2text
; Extract high-order 5 bits (X or Y, depending on lastc)
tekgh2: and ax,1Fh ; Just 5 bits
mov cl,5
shl ax,cl ; Shift over 5 bits
cmp lastc,loy ; was last coordinate a low-y?
je tekgh3 ; e = yes, parse hix
mov tek_hiy,ax ; this byte has HIY
mov lastc,hiy
clc
ret
tekgh3: mov tek_hix,ax ; This byte has HIX
mov lastc,hix
clc
ret
tekgh4: and al,1Fh ; Just 5 bits
mov tek_lox,al
mov lastc,lox
mov ax,tek_hix ; Combine HIX*32
or al,tek_lox ; with LOX
mov bx,tek_hiy ; Same for Y
or bl,tek_loy
stc ; set c to say completed operation
ret
TEKXYC endp
TEKRLIN proc near ; RS relative line drawing
cmp al,' ' ; Pen up command?
jne tekrli1 ; ne = no, try pen down
mov visible,0 ; do invisible movements
jmp short tekrli2 ; do the command
tekrli1:cmp al,'P' ; pen down command?
jne tekrli3 ; ne = no, return to text mode
mov visible,1 ; set visible moves
tekrli2:mov ax,x_coord ; PC x coordinate of pen
mov bx,y_coord ; y coordinate
call pctotek ; get current pen position in Tek coor
mov cl,0 ; invisible, moveto
call tekdraw ; move that point, set oldx and oldy
mov ttstate,offset tekinc ; next get incremental movement cmds
ret
tekrli3:mov visible,0 ; bad char, reset visibility
push prestate
pop ttstate ; restore previous state
jmp tektt5 ; deal with the break char
TEKRLIN endp
; interpret RS inc plot command byte
TEKINC proc near ; get movement character and do cmd
cmp al,'A' ; move right?
jne tekinc1 ; ne = no
inc oldx ; adjust beam position
jmp short tekinc9
tekinc1:cmp al,'E' ; move right and up?
jne tekinc2 ; ne = no
inc oldx
inc oldy
jmp short tekinc9
tekinc2:cmp al,'D' ; move up?
jne tekinc3 ; ne = no
inc oldy
jmp short tekinc9
tekinc3:cmp al,'F' ; move left and up?
jne tekinc4 ; ne = no
dec oldx
inc oldy
jmp short tekinc9
tekinc4:cmp al,'B' ; move left?
jne tekinc5 ; ne = no
dec oldx
jmp short tekinc9
tekinc5:cmp al,'J' ; move left and down?
jne tekinc6 ; ne = no
dec oldx
dec oldy
jmp short tekinc9
tekinc6:cmp al,'H' ; move down?
jne tekinc7 ; ne = no
dec oldy
jmp short tekinc9
tekinc7:cmp al,'I' ; move right and down?
jne tekincb ; ne = no, bad command
inc oldx
dec oldy
tekinc9:cmp oldx,0 ; too far left?
jge tekinc10 ; ge = no
mov oldx,0 ; else stop at the left margin
tekinc10:cmp oldx,maxtekx-1 ; too far left?
jle tekinc11 ; le = no
mov oldx,maxtekx-1 ; else stop that the left margin
tekinc11:cmp oldy,maxteky-1 ; above the top?
jle tekinc12 ; le = no
mov oldy,maxteky-1 ; else stop at the top
tekinc12:cmp oldy,0 ; below the bottom?
jge tekinc13 ; ge = no
mov oldy,0 ; else stop at the bottom
tekinc13:mov ax,oldx ; ax is vector x end point
mov bx,oldy ; bx is vector y end point
mov cl,visible
call tekdraw ; move/draw to that point
ret
tekincb:push prestate ; bad character, exit inc plot mode
pop ttstate ; new state is previous state
mov visible,0
jmp tektt5 ; reparse the bad char
TEKINC endp
; Routine to trigger the crosshairs, wait for a key to be struck, and send
; the typed char (if printable ascii) plus four Tek encoded x,y position
; coordinates and then a carriage return.
; ax, cx, xcross, ycross operate in PC coordinates.
CROSHAIR PROC NEAR
push linepat ; save line drawing pattern
mov linepat,0ffffh ; reset line type to solid
mov ax,xmax ; right margin minus 7 dots
add ax,7
mov temp,ax ; right margin dot
crosha1:call crosdraw ; draw the cross-hairs
call iseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov ah,coninq ; DOS, quiet read char
int dos
push ax ; save char for later
call crosdraw ; erase cross hairs
pop ax
or al,al ; ascii or scan code returned
jnz arrow5 ; nz = ascii char returned
call iseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov ah,coninq ; read scan code
int dos
cmp al,0 ; Control-Break?
jne crosha3 ; ne = no, something else
crosha2:pop linepat ; restore line pattern
ret ; exit crosshairs mode
crosha3:cmp al,homscn ; is it 'home'?
jne arrow1 ; ne = no, try other keys
mov ax,temp ; right margin
shr ax,1 ; central position
mov xcross,ax ; save PC coord for crosshair
mov ax,ybot ; last scan line
shr ax,1
mov ycross,ax ; this is the center of the screen
jmp crosha1 ; home the crosshairs
arrow1: cmp al,lftarr ; left arrow?
jne arrow2 ; ne = no
mov cx,-1 ; left shift
jmp short xkeys
arrow2: cmp al,rgtarr ; right arrow?
jne arrow3 ; ne = no
mov cx,1 ; right shift
jmp short xkeys
arrow3: cmp al,uparr ; up arrow?
jne arrow4 ; ne = no
mov cx,-1 ; up shift
jmp short vertkey
arrow4: cmp al,dnarr ; down arrow?
jne badkey ; ne = no, ignore it
mov cx,1 ; down shift
jmp short vertkey
badkey: call beep ; tell user we don't understand
jmp crosha1 ; keep going
; Shifted keys yield ascii keycodes
arrow5: cmp al,'C' and 1fh ; Control-C?
je crosha2 ; e = yes, exit crosshairs mode now
cmp al,shlftarr ; shifted left arrow?
jne arrow6 ; ne = no
mov cx,-10 ; big left shift
jmp short xkeys
arrow6: cmp al,shrgtarr ; shifted right arrow?
jne arrow7 ; ne = no
mov cx,10 ; big right shift
jmp short xkeys
arrow7: cmp al,shuparr ; shifted up arrow?
jne arrow8 ; ne = no
mov cx,-10 ; big up shift
jmp short vertkey
arrow8: cmp al,shdnarr ; shifted down arrow?
jne charkey ; ne = no, send this key as is
mov cx,10 ; big down shift
jmp short vertkey
xkeys: add cx,xcross ; add increment
jns noxc ; gone too far negative?
mov cx,0 ; yes - then make it 0
noxc: cmp cx,temp ; too far right?
jb xdraw9 ; b = no
mov cx,temp ; yes - then make it the right
xdraw9: mov xcross,cx ; new x value for cross hairs
jmp crosha1 ; and redraw
vertkey:add cx,ycross ; adjust cx
jns noyc ; gone negative?
mov cx,0 ; yes then make 0
noyc: cmp cx,ybot ; too high?
jb yok
mov cx,ybot ; make it maximum
yok: mov ycross,cx ; save new y crosshair
jmp crosha1 ; and redraw
charkey:call clrbuf ; purge received data to date
call outmodem ; send the break character
mov ax,xcross ; set beam to xcross,ycross
mov bx,ycross ; must convert to Tek coordinates
call pctotek ; scale from PC screen coord to Tek
push ax ; save around drawing
push bx
mov cx,0 ; just a move
call tekdraw ; moveto ax,bx in Tek coord
pop bx ; recover Tek y
pop ax ; recover Tek x
call sendpos ; send position report to host
pop linepat ; recover current line drawing pattern
mov ttstate,offset tektxt ; Go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
ret
CROSHAIR ENDP
; CROSDRAW draws cross-hairs by XORing cross with picture.
; xcross and ycross are in PC coordinates.
CROSDRAW PROC NEAR
mov si,xcross ; move to (xcross, ycross-10)
mov di,ycross
sub di,10 ; half the size of the cross
jns crosd1 ; no sign bit means ok
mov di,0 ; else limit to start of screen
crosd1: mov ax,si ; next, draw to (xcross, ycross+10)
mov bx,ycross ; make bottom stroke
add bx,10
cmp bx,ybot ; too large?
jbe crosd2 ; be = no
mov bx,ybot ; vertical line to (xcross,ybot)
crosd2: mov cx,0ffh ; invert pixels
call line ; and draw vertical
sub si,12 ; move to (xcross-12, ycross)
jns crosd3 ; no sign means ok
mov si,0 ; else limit to start of line
crosd3: mov di,ycross
mov bx,di
mov ax,xcross ; draw to (xcross+12, ycross)
add ax,12
cmp ax,temp ; temp is right margin, too large?
jbe crosd4 ; be = no, ok
mov ax,temp ; max x value
crosd4: mov cx,0ffh ; set XOR code
call line ; draw to (xcross+12, ycross)
ret
CROSDRAW ENDP
; SENDPOS sends position of cross-hairs to the host.
; ax has Tek X and bx has Tek Y coord of center of crosshair
SENDPOS PROC NEAR
push bx ; preserve register
call sendxy ; send x coord
pop ax
call sendxy ; send y coord
mov al,cr ; follow up with cr
call outmodem
ret
SENDPOS ENDP
; SENDXY sends value of ax as Tek encoded bytes
; ax is in Tek coordinates
SENDXY PROC NEAR
shl ax,1
shl ax,1 ; move all but lower 5 bits to ah
shl ax,1
shr al,1
shr al,1 ; move low five bits to low 5 bits
shr al,1
or ah,20h ; make it a printing char as per TEK
xchg al,ah ; send high 5 bits first
call outmodem
xchg al,ah ; then low five bits
or al,20h
call outmodem
xchg ah,al ; al is first sent byte
ret
SENDXY ENDP
SENDID PROC NEAR ; Pretend VT100 with graphics option
mov bx,IDSEQ ; Get addr of string
sndid1: mov al,[bx] ; Get char from sequence
cmp al,0 ; End of sequence?
jz sndid0 ; Yes, return
call OUTMODEM ; Send it out the port
inc bx
jmp sndid1
sndid0: ret
SENDID ENDP
; SENDSTAT - send status and cursor position to host
SENDSTAT PROC NEAR
mov al,STATUS ; get tek status
or al,20h ; make it printable
call OUTMODEM ; and send it
mov ax,oldx ; now send x coordinate (oldx is Tek)
call SENDXY
mov ax,oldy ; and y coordinate (oldy is Tek coord)
call SENDXY
mov al,cr ; end with a cr
call OUTMODEM
ret
SENDSTAT ENDP
; routine to send al to the modem port
OUTMODEM PROC NEAR
push ax
mov ah,al
call outchr ; outchr reads from ah
nop ; ignore errors
nop
nop
pop ax
ret
OUTMODEM ENDP
; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
; for both input and output.
pctotek proc near
mul xdiv ; scale from PC screen coord to Tek
div xmult
xchg bx,ax ; save Tek x coord in bx
neg ax ; y axis. Turn upside down for Tek
add ax,ybot
mul ydiv ; scale y from PC screen coord to Tek
div ymult
xchg ax,bx ; ax has X, bx has Y in Tek coords
ret
pctotek endp
; Routine to output character in AL to the screen.
OUTSCRN PROC NEAR ; Output one character to the screen
cmp bypass,0 ; GIN mode bypass off?
je outscp ; e = yes
ret ; else ignore characters
outscp: ; Set Translation Input filter
cmp rxtable+256,0 ; translation turned off?
je outsct ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
and al,7fh ; retain only lower seven bits
pop bx
outsct: mov si,ybot ; get last scan line
inc si ; number of scan lines
sub si,y_coord ; minus where char bottom needs to go
jnc outscc ; nc = enough space for char
; else give "More >" message
push ax ; save current char
push cx
mov cx,mormsglen ; characters in More message
mov ax,cx
shl ax,1
shl ax,1
shl ax,1 ; times 8 bits/character
neg ax ; (note: leave last char cell empty)
add ax,xmax ; right justify
mov x_coord,ax ; set starting x dot
mov ax,ybot
mov y_coord,ax ; set starting y line
mov ccode,1 ; write in foreground colors
push cx
mov al,DEL ; fill all pixels
outscm1:call putc ; write
loop outscm1
pop cx
push cx
mov al,BS ; backup to overwrite with More text
outscm2:call putc
loop outscm2
pop cx
mov ccode,0 ; main text in background colors
mov si,offset moremsg ; give More message
outsclf:cld
lodsb ; read a byte from string
call putc ; display the string
loop outsclf ; repeat for all string chars
pop cx
mov ccode,1 ; restore normal foreground coloring
call iseof ; EOF on redirected stdin?
jc outscl3 ; c = yes, proceed anyway
mov ah,coninq ; read keyboad via DOS
int dos ; wait for keystroke
or al,al ; scan code being returned?
jne outscl3 ; ne = no
mov ah,coninq ; clear away scan code too
int dos
outscl3:call tekcls ; clear the screen
pop ax ; recover current character
cmp al,lf ; just a line feed?
jne outscc ; ne = no, display it
ret ; else ignore the line feed
outscc: push ax
mov ax,xmax
cmp x_coord,ax ; beyond right margin?
jbe outsc3 ; be = no
mov al,cr ; else simulate cr/lf
call putc ; before displaying current char
mov al,lf
call putc
outsc3: pop ax
call putc ; routine to draw characters
ret
OUTSCRN ENDP
; TEKCLS routine to clear the screen.
; Entry point tekcls1 clears screen without resetting current point.
TEKCLS PROC NEAR
cmp tekflg,0 ; Tek sub mode active yet?
jne tekcls0 ; ne = yes
ret ; else ignore this call
tekcls0:mov x_coord,0 ; starting text coordinates
mov y_coord,8
mov oldx,0 ; assumed cursor starting location
mov oldy,maxteky ; top right corner (Tek coord)
mov scalex,0 ; clear last plotted point (PC coord)
mov scaley,0
mov lastc,0 ; last parsed x,y coordinate
mov visible,0 ; make lines invisible
mov linepat,0ffffh ; reset line pattern to solid
mov ccode,1 ; reset to ordinary writing
mov bypass,0 ; clear bypass condition
mov ttstate,offset tektxt ; do displayable text
push ax
mov ax,xmax ; right margin minus 7 dots
add ax,7 ; right most dot
shr ax,1 ; central position
mov xcross,ax ; save PC coord for crosshair
mov ax,ybot ; last scan line
shr ax,1
mov ycross,ax ; this is the center of the screen
pop ax
tekcls1:push ax ; save registers
push cx
cmp graph_mode,hercules ; Hercules?
jne tekcls2 ; ne = no
call hgraf ; set Hercules board to Graphics mode
jmp tekcls7
tekcls2:mov di,0 ; point to start of screen, di=row
call psetup ; setup graphics routine and es:di
mov cx,4000h ; CGA, 200 lines times 80 bytes worth
cmp graph_mode,cga ; cga?
je tekcls3 ; e = yes
mov cx,8000h ; Olivetti, 400 lines times 80 bytes
cmp graph_mode,olivetti ; AT&T-Olivetti?
je tekcls3 ; e = yes
cmp graph_mode,toshiba ; Toshiba?
je tekcls3 ; e = yes
cmp graph_mode,vaxmate ; VAXmate?
jne tekcls4 ; ne = no
tekcls3:cld ; clear screen directly of text stuff
mov al,0 ; color is black
rep stosb ; clear the bytes
jmp short tekcls7
tekcls4:cmp graph_mode,ega ; EGA?
je tekcls5 ; e = yes
cmp graph_mode,monoega ; EGA with mono display?
je tekcls5 ; e = yes
cmp graph_mode,colorega ; EGA with medium resolution monitor?
je tekcls5 ; e = yes
jmp short tekcls6 ; else use Bios
tekcls5: ; EGA clear screen quickly
mov ax,0ff08h ; set all 8 bits to be changed
call ega_gc ; set bit mask register accordingly
mov cx,ybot ; last scan line
inc cx ; number of scan lines
mov ax,80 ; bytes per scan line
mul cx
mov cx,ax ; cx = number of bytes to clear
mov al,gbcol ; select background colour
cld
rep stosb ; write backgound color
jmp short tekcls7
tekcls6:push es ; clear screen by scrolling up
call cmblnk ; clear screen, for Environments
pop es
tekcls7:mov si,0 ; starting x (in case screen is
mov di,0 ; starting y cleared by user)
pop cx
pop ax
ret
TEKCLS ENDP
; Routine to draw a line on the screen, using TEKTRONIX coordinates.
; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line
TEKDRAW PROC NEAR
mov si,scalex ; get old x already scaled
mov di,scaley ; get old y already scaled
call scale ; scale new end point to PC coords
cmp cl,0 ; invisible drawing?
je moveto ; z = just move, skip draw part
call LINE ; draw the line
moveto: mov x_coord,ax ; update text coordinates to match
mov y_coord,bx ; last drawn point
ret
TEKDRAW ENDP
; Scale TEKTRONIX coordinates to the currently defined screen coordinates
; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
; to PC coordinates by this procedure.
SCALE PROC NEAR
push dx
push si
mov oldx,ax ; save current Tek x for next draw
mov oldy,bx ; save current Tek y for next draw
mul xmult ; scale x-coord
mov si,xdiv ; get the divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div xdiv
push ax
mov ax,bx
mul ymult ; scale y-coord
mov si,ydiv ; get divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div ydiv
mov bx,ybot
sub bx,ax ; Put new Y in right reg
jns scale3 ; ns = not too far
mov bx,0
scale3: pop ax ; Put new X in right reg
mov scalex,ax ; save scaled values
mov scaley,bx
pop si
pop dx
ret
SCALE ENDP
; LINE Subroutine to plot a line with endpoints in AX,BX and SI,DI.
; fast line drawing routine for the IBM PC
;
; Registers at CALL
; -----------------
; SI=Start X coord, all in PC coordinates
; DI=Start Y coord
; AX=End X coord
; BX=End Y coord
; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert
; BP= line drawing pattern (is changed here by rotation)
; registers are all unchanged
LINE PROC NEAR
push ax
push bx
push cx
push dx
push si
push di
push es
mov bp,linepat ; store active line pattern word in BP
mov ccode,cl ; save color code in ccode for use by plot()
; first get coord to achieve increasing x; deltax >= 0
sub ax,si ; deltax = x2 - x1
jge line1 ; ge = going to the right, as desired
neg ax ; make deltax non-negative
sub si,ax ; swap the x coordinates
xchg bx,di ; swap the y coordinates too
; second, compute deltay. ax = deltax, si = x1
line1: sub bx,di ; deltay = y2 - y1
call psetup ; setup display adapter for plotting
; and setup es:di to screen memory
; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
; We arrange matters such that both deltas are non-negative.
cmp bx,0 ; deltay
jge line2 ; ge = non-negative
neg linelen
neg bx ; make non-negative
line2: cmp bx,ax ; |deltay| versus |deltax|
jbe shallow ; be = do shallow algorithm
jmp steep ; else do steep algorithm
; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
shallow:add bx,bx ; bx = 2*deltay
mov cx,ax ; cx = number of steps (deltax here)
inc cx ; loop dec's cx before testing
mov dx,bx ; dx holds error
sub dx,ax ; error = 2*deltay - deltax
add ax,ax ; ax = 2*|deltax|
shal1: call plotptr ; Plot(x,y)
cmp dx,0
jle shal2 ; le = error <= 0
call pincy ; increment y by one scan line
sub dx,ax ; error = error - 2*deltax
shal2: add dx,bx ; error = error + 2*deltay
inc si ; x = next dot right
loop shal1
shal3: jmp short plotex
; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
steep: add ax,ax ; ax = 2*deltax
mov dx,ax ; dx holds error
sub dx,bx ; error = 2*deltax(bx) - deltay (bx)
mov cx,bx ; cx = number of steps (deltay here)
inc cx ; loop dec's cx before testing
add bx,bx ; bx = 2*|deltay|
stee1: call plotptr ; Plot(x,y) x = ax, y = di
cmp dx,0
jle stee2 ; le error <= 0
inc si ; x = next dot right
sub dx,bx ; error = error - 2*deltay
stee2: add dx,ax ; error = error + 2*deltax
call pincy ; increment y
loop stee1
stee3:;;;jmp plotex
plotex: mov ccode,1 ; reset to do foreground coloring
pop es
pop di
pop si
pop dx ; restore the world
pop cx
pop bx
pop ax
ret
LINE ENDP
;;;;;;; EGA plot support routines
psetupe proc near ; EGA setup for plotting
push ax
mov linelen,80 ; for y going down screen by pincy
mov ax,segscn ; set es to screen memory segment
mov es,ax
mov ax,0205h ; mode: write mode 2
call ega_gc
mov ax,0003h ; assume writing bits directly
cmp ccode,0ffh ; inverting bits?
jne psete2 ; ne = no
mov ax,1803h ; then say XOR the bits
psete2: call ega_gc ; set controller
mov ax,80 ; compute starting point in regen buff
mul di
mov di,ax ; di = di * 80
pop ax
ret
psetupe endp
pincye proc near ; EGA inc y
add di,linelen ; includes sign of deltay
ret
pincye endp
pltega proc near ; EGA plot(x,y). x is in si, y is in di
rol bp,1 ; rotate line pattern
jnc pltega1 ; nc = no bit to be plotted
push bx
push si
push di
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting point in regen buffer
and bx,0007h ; leave lower 3 bits for bit in byte
mov bh,masktab[bx] ; 0-7 into bit mask in byte, x pos
mov bl,ccode ; get line type code
call ega_plt
pop di
pop si
pop bx
pltega1:ret
pltega endp
;;;;;;;; CGA plot support routines
; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
psetupc proc near ; CGA setup for plotting
push ax
push cx
mov linelen,80 ; 80 bytes per scan line
mov cx,segscn
mov es,cx
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; half the lines in each bank
mov ax,80 ; 80 bytes per line
mul di
mov di,ax ; di = di * 80 / 2
test cx,1 ; even or odd line
jz psetc1 ; z = even
add di,2000h ; offset to odd bank (seg 0ba00h)
psetc1: and di,3fffh
pop cx
pop ax
ret
psetupc endp
pincyc proc near ; CGA inc y
cmp linelen,0 ; increasing or decreasing y?
jl pinyc2 ; l = decreasing
cmp di,2000h ; in upper bank now?
jb pinyc1 ; b = no, in lower bank
add di,linelen ; add a line
pinyc1: add di,2000h ; switch banks
and di,3fffh ; roll over address
ret
pinyc2: cmp di,2000h ; in upper bank now?
jae pinyc4 ; ae = yes
add di,linelen ; subtract a line
pinyc4: add di,2000h ; switch banks
and di,3fffh ; roll over address
ret
pincyc endp
pltcga proc near ; CGA plot(x,y). x is in si, y is in di
push bx ; used for HGA plot also.
push si
push di
rol bp,1 ; rotate line pattern
jnc pltcg3 ; nc = no bit to be plotted
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting point in regen buffer
and bx,0007h ; leave lower 3 bits for bit in byte
; di = offset in regen buffer
mov bh,masktab[bx] ; 0-7 into bit mask in byte. x position
mov bl,ccode ; get line type code
cmp bl,1 ; draw the bit?
jne pltcg1 ; ne = no
or es:[di],bh ; drawn
jmp short pltcg3
pltcg1: cmp bl,0 ; draw in background (erase)?
jne pltcg2 ; ne = no
not bh
and es:[di],bh ; erase the dots
jmp short pltcg3
pltcg2: xor es:[di],bh ; xor in this color
pltcg3: pop di
pop si
pop bx
ret
pltcga endp
;;;;;;; HGA plot support routines
; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
; left most dot in the high bit, 90 bytes per scan line, scan line segments
; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
; higher for the rest.
psetuph proc near ; HGA setup for plotting
push ax
push cx
mov linelen,90 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; quarter the lines in each bank
shr di,1
mov ax,90
mul di
mov di,ax ; di = di * 90 / 4
and cx,3 ; compute bank from 2 lsb of line num
jcxz pseth2 ; z means it is in bank 0 (0b000h)
pseth1: add di,2000h ; add offset for each bank
loop pseth1 ; do cx times
pseth2: pop cx
pop ax
ret
psetuph endp
pincyh proc near ; HGA inc y, step offset of line
cmp linelen,0 ; increasing y?
jg pinyh2 ; g = yes
cmp di,2000h ; in lowest for four banks?
ja pinyh1 ; a = no
add di,linelen ; yes, add a line
pinyh1: add di,6000h ; move back by adding a lot
and di,7fffh ; roll over address
ret
pinyh2: cmp di,6000h ; in top most bank?
jb pinyh4 ; b = no
add di,linelen ; yes, first add a line
pinyh4: add di,2000h ; switch to next bank
and di,7fffh ; roll over address
ret
pincyh endp
;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
; writing. This is a monographic display.
psetupo proc near ; setup for plotting
push ax
push cx
mov linelen,80 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; quarter the lines in each bank
shr di,1
mov ax,80
mul di
mov di,ax ; di = di * 80 / 4
and cx,3 ; compute bank from 2 lsb of line num
jcxz pseto2 ; z means it is in bank 0 (0b800h)
pseto1: add di,2000h ; add offset for each bank
loop pseto1 ; do cx times
pseto2: pop cx
pop ax
ret
psetupo endp
;;;;;;;; Monochrome, simulate dots with text char
psetupm proc near
mov linelen,1 ; 80 characters but one line
ret
psetupm endp
pltmon proc near ; Monochrome dot plot
mov x_coord,si ; put dot at row=di, col=si, PC Coord
mov y_coord,di
push ax
mov al,'+' ; our dot character
call mputc ; display text char
pop ax
ret
pltmon endp
pincym proc near ; Monochrome inc y
add di,linelen ; includes sign
ret
pincym endp
; GPUTC - a routine to send text characters from font to true graphics boards
; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
gputc proc near
cmp al,' ' ; control character?
jae gputc1 ; ae = no, display the char
jmp putctrl ; else handle controls at putctrl
gputc1: push ax ; first save some registers
push bx
push cx
push es
push di
mov bl,al ; now BL has char to be displayed
and bl,7fh ; no high bits allowed here
; set board mode
mov di,y_coord ; get current y coord (char bottom)
sub di,8 ; start 8 lines higher
jnc gputc2 ; nc = ok
mov di,0 ; move up to first line
mov y_coord,8 ; and reset scan line indicator
gputc2: call psetup ; enter with di=line number, sets es:di to
; start of line in display buf and
; sets byte-wide plot mode
mov ax,x_coord ; compute regen buffer byte
shr ax,1 ; want x_coord/8 for bytes along line
shr ax,1
shr ax,1
add di,ax ; byte in regen buffer
xor bh,bh
sub bx,32 ; characters in font start at 32
shl bx,1
shl bx,1 ; 8 bytes per char - hence * 8
shl bx,1
mov cx,8 ; 8 bytes (scan lines) to transfer
call gcplot ; call character plot routine
call incx ; move to next char position
pop di
pop es
pop cx
pop bx
pop ax
ret
gputc endp
putctrl proc near ; CONTROL CHARS = cursor movement
push ax ; save character
cmp al,FF ; formfeed?
jne putct0 ; ne = no
call TEKCLS ; FF clears the screen
jmp putctx
putct0: cmp al,BS ; BS? sends (logical) cursor back one
jne putct2 ; ne = no, try next
mov ax,x_coord
sub ax,8 ; so delete 8 dots (move left)
jns putct1 ; ns = non-negative
mov ax,0 ; but not less than 0
putct1: mov x_coord,ax ; and replace x coordinate
mov al,' ' ; send a space
call putc
sub x_coord,8 ; restore cursor
jmp putctx
putct2: cmp al,tab ; tabs move forward one char position
jne putct4 ; ne = not a tab
call incx ; let incx move cursor right one col
jmp putctx
putct3: mov x_coord,ax
jmp putctx
putct4: cmp al,cr ; <CR> means go to beginning of line
jne putct5
mov x_coord,0 ; zero the x coordinate
jmp putctx
putct5: cmp al,lf ; <LF> means go down 8 pixels (1 line)
jne putct7 ; ne = not LF
add y_coord,8 ; border managed by outscrn and incx
jmp putctx
putct7: cmp al,vt ; <VT> move up screen 1 line (8 pixels)
jne putctx
sub y_coord,8 ; subtract one line (8 pixels)
jnc putctx ; nc = space left
mov y_coord,8 ; else set to top of screen
putctx: pop ax
ret
putctrl endp
mputc proc near ; MONO put char in AL via Bios
push ax ; updates x_coord,y_coord with
push bx ; new cursor position
push cx
push dx
mov ah,0 ; marker for cursor setting not needed
cmp al,' ' ; control code?
jae mputc1 ; ae = no, printable
call putctrl ; do cursor arithmetic
mov ah,1 ; marker to set cursor but no display
mputc1: push ax ; save char and marker
mov cl,3 ; char cell is 8 x 8 dots
mov ax,x_coord ; get resulting cursor PC positions
shr ax,cl
mov dl,al ; column
mov ax,y_coord
sub ax,8 ; minus 8 dots, like other modes
jnc mputc2 ; nc = non-negative
mov ax,0 ; else start at the top
mov y_coord,8 ; here too
mputc2: shr ax,cl
mov dh,al ; row
mov ah,2 ; set cursor to x_coord,y_coord
mov bh,0 ; page 0
int screen
pop ax
cmp ah,0 ; write a char in al?
jne mputcx ; ne = no
mov ah,09h ; write char at cursor postion
mov cx,1 ; just one char
mov bh,0 ; page 0
mov bl,gfcol ; foreground coloring
int screen
inc dl ; next column
mov ah,2 ; set real cursor ahead of last char
int screen
call incx ; move logical cursor
mputcx: pop dx
pop cx
pop bx
pop ax
ret
mputc endp
incx proc near ; move the logical cursor right
mov ax,x_coord ; shift the (logical) cursor right
add ax,8 ; one character cell
mov x_coord,ax
cmp ax,xmax ; at end of the line?
jbe incx1 ; b = no
mov x_coord,0 ; wrap to next line
add y_coord,8 ; next row
mov ax,ybot ; last scan line
cmp ax,y_coord ; below bottom line?
jge incx1 ; ge = no
mov y_coord,ax ; set to bottom row
mov al,lf ; simulate a line feed operation
call outscrn ; invoke More message
incx1: ret
incx endp
; EGA Character plot routine. Enter with bx pointing at font array for char
; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
; ccode: 0=plot in background colors, 1=foreground, 0ffh=xor with screen
gcega proc near
gcega1: mov al,font[bx] ; EGA byte plot: get bits from font
push bx
;;;;; mov bh,0ffh ; write these bits to clear field
;;;;; mov bl,0 ; in background coloring
;;;;; call ega_plt ; plot a byte
mov bh,al ; set bit pattern of character
mov bl,ccode ; plot in back/fore/xor (ccode) colors
call ega_plt ; byte plot routine for EGA systems
pop bx
inc bx ; next byte of char pattern
call pincy ; next scan line (linelen is preset)
loop gcega1
ret
gcega endp
; General Character plot routine. Enter with bx pointing at font array for
; char, cx = number of bytes in char font, es:di = screen memory.
; Worker for gputc.
gcgen proc near
gcgen1: mov al,font[bx] ; Non-EGA systems: get bits from font
cmp ccode,1 ; write in foreground?
je gcgen2 ; e = yes
xor es:[di],al ; background or xor (same)
jmp short gcgen3
;;;; mov es:[di],al ; write desired pattern (no overwrite)
gcgen2: OR es:[di],al ; write desired pattern (no overwrite)
gcgen3: inc bx ; point to next byte of char pattern
call pincy ; next scan line (linelen is preset)
loop gcgen1 ; and repeat until complete
ret
gcgen endp
; routines to manipulate ega graphics controller and mode register
; command code in al, value in ah - destroys al and dx
ega_gc proc near ; ega graphics controller
mov dx,3ceh
out dx,al ; output command code
inc dx ; dx is now data port
mov al,ah ; get value to al
out dx,al ; output value
ret
ega_gc endp
ega_md proc near ; ega mode controller
mov dx,3c4h
out dx,al ; output command code
inc dx ; dx is now data port
mov al,ah ; get value to al
out dx,al ; output value
ret
ega_md endp
; Plot eight pixels using an EGA board
; Enter with ES:[DI] pointing to screen address of byte,
; bh has pattern of bits to be set, bl has attributes:
; 0 = draw in background color, 1 = draw in foreground color,
; 0ffh = XOR with current dot colors.
; registers preserved
ega_plt proc near
push ax
push dx
mov al,8 ; command to set bit mask register
mov ah,bh ; get bits to be modified (1)
call ega_gc ; unprotect those bit positions
mov ah,gfcol ; get foreground colour
cmp bl,1 ; draw in foreground?
je ega2 ; ne = no
mov ah,gbcol ; get grahics background colour
cmp bl,0ffh ; do an XOR?
jne ega2 ; ne = no
mov ah,0ffh ; XOR, touch all color bits
ega2: mov al,es:[di] ; latch byte
mov es:[di],ah ; set the byte
pop dx
pop ax
ret
ega_plt endp
; routine to set Hercules card to graphics mode - both pages are enabled
HGRAF PROC NEAR
push ax
push bx ; save used registers
push cx
push si
mov al,grph ; graph mode
lea si,gtable ; requires graphics table
mov bx,0
mov cx,4000h ; clear 4000h words
call setmd ; and set the mode
pop si
pop cx
pop bx
pop ax
ret
HGRAF ENDP
; set Hercules card to text mode
HTEXT PROC NEAR
push ax
push bx
push cx
push si
mov al,text ; text mode
lea si,ttable ; requires text table
mov bx,0720h ; blank value (space, white on black)
mov cx,2000 ; whole screen to clear (80*25)
call setmd ; set the mode
pop si
pop cx
pop bx
pop ax
ret
HTEXT ENDP
; Hercules mode set - called from HTEXT and HGRAF
SETMD PROC NEAR
push dx
push ax
mov dx,config ; configuration port
mov al,genable ; allow graphics mode to be set
out dx,al
pop ax
push ax
push cx ; save count
mov dx,cntrl ; control port
out dx,al ; set to text or graphics
mov dx,index ; send 12 bytes from table to 6845
mov cx,12 ; number of registers to load
xor ah,ah ; start with register 0 of 6845
cld
setmd1: jmp $+2 ; small pause for hardware
mov al,ah ; ah is counter
out dx,al ; set register
inc dx ; point to data port
lodsb ; get next byte in table
jmp $+2 ; small pause for hardware
out dx,al ; and send to 6845
inc ah ; next register
dec dx ; point to register port
loop setmd1 ; and continue 'til cx=0
pop cx ; recover count
cld
push di
push es
mov ax,segscn ; start of screen
mov es,ax
xor di,di
mov ax,bx ; get blanking character
rep stosw ; store blanking char in whole screen
pop es
pop di
mov dx,cntrl ; now to re-enable screen
pop ax ; get mode
or al,scrn_on ; enable screen
out dx,al
pop dx
ret
SETMD ENDP
teksave proc near ; saves graphics screen from page 0 to page 1
push si
push di
cmp gpage,0 ; only graphics page 0 on display board?
je teksavx ; e = yes, no saving possible here
mov si,segscn ; segment (!) of current screen
cmp graph_mode,ega
je teksav1
cmp graph_mode,monoega
je teksav1
cmp graph_mode,colorega
je teksav1
cmp graph_mode,hercules
je teksav2
jmp short teksavx ; else nothing
teksav1:mov di,segega+800h ; EGA page 1 screen segment
call egasr ; call common save/restore code
jmp short teksavx
teksav2:mov di,seghga+800h ; Hercules page 1 screen segment
call hgasr ; call common save/restore code
teksavx:pop di
pop si
ret
teksave endp
tekrest proc near ; saves graphics screen of page 0 in page 1
push si
push di
cmp gpage,0 ; only graphics page 0 on display board?
jne tekres0 ; ne = no, more so work to do here
call tekcls1 ; else clear the screen to color it
jmp short tekresx ; and exit
tekres0:mov di,segscn ; segment (!) of new graphics screen
cmp graph_mode,ega
je tekres1
cmp graph_mode,monoega
je tekres1
cmp graph_mode,colorega
je tekres1
cmp graph_mode,hercules
je tekres2
jmp short tekresx ; else nothing
tekres1:mov si,segega+800h ; segment of EGA page 1
call egasr ; call common save/restore code
jmp short tekresx
tekres2:mov si,seghga+800h ; segment of Hercules page 1
call hgasr ; call common save/restore code
tekresx:pop di
pop si
ret
tekrest endp
egasr proc near ; common code for Tek ega save/restore ops
push ax
push cx
push dx
mov ax,0f00h ; enable 4 plane set/resets
call ega_gc ; set controller
mov ax,0f01h ; enable Set/Reset register
call ega_gc
mov ax,0f02h ; set color compare register for 4 planes
call ega_gc
mov ax,0905h ; set mode reg: write latches, read mode
call ega_gc
mov ax,0ff02h ; enable all planes
call ega_md
mov cx,ybot ; last scan line
inc cx ; number of scan lines
mov ax,80 ; bytes per scan line
mul cx
mov cx,ax
push es ; save es
push ds ; save ds
mov es,di ; destination, set es to video memory
mov ds,si ; source, set ds to video memory
xor si,si ; clear offset fields
xor di,di
cld
rep movsb ; copy from page [si] to page [di]
pop ds ; recover ds
pop es ; and other registers
mov ax,0000h ; disable 4 plane set/resets
call ega_gc ; set controller
mov ax,0001h ; disable Set/Reset register
call ega_gc ; set controller
mov ax,0002h ; disable color compare register
call ega_gc
mov ax,1005h ; set mode reg: write latches, odd/even
call ega_gc
pop dx
pop cx
pop ax
ret
egasr endp
hgasr proc near ; Hercules save restore screen
push cx
mov cx,4000h ; number of words to move
push es ; save es
push ds ; save ds
mov es,di ; destination, set es to video memory
mov ds,si ; source, set ds to video memory
xor si,si ; clear offset fields
xor di,di
cld
rep movsw ; copy from page [si] to page [di]
pop ds ; recover ds
pop es ; and other registers
pop cx
ret
hgasr endp
code ends
end